home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / metasploit / msfconsole < prev    next >
Text File  |  2006-06-30  |  25KB  |  971 lines

  1. #!/usr/bin/perl
  2. ###############
  3.  
  4. ##
  5. #         Name: msfconsole
  6. #       Author: H D Moore <hdm [at] metasploit.com>
  7. #       Author: spoonm <ninjatools [at] hush.com>
  8. #  Description: Console shell interface to the Metasploit Exploit Framework
  9. #      Version: $Revision: 1.99 $
  10. #      License:
  11. #
  12. #      This file is part of the Metasploit Exploit Framework
  13. #      and is subject to the same licenses and copyrights as
  14. #      the rest of this package.
  15. #
  16. ##
  17.  
  18. require 5.6.0;
  19.  
  20. use strict;
  21. use FindBin qw{$RealBin};
  22. use lib "$RealBin/lib";
  23. use vars qw($VERSION);
  24. use IO::Socket;
  25. use POSIX;
  26. use Getopt::Std;
  27. use Sys::Hostname;
  28.  
  29. use Pex::PsuedoShell;
  30. use Msf::TextUI;
  31. use Pex;
  32.  
  33. no utf8;
  34. no locale;
  35.  
  36. Msf::UI::ActiveStateSucks();
  37. Msf::UI::BrokenUTF8();
  38.  
  39. my $ui = Msf::TextUI->new($RealBin);
  40. my $FRAMEVERSION = $ui->Version;
  41. my $VERSION = '$Revision: 1.99 $';
  42.  
  43. $SIG{'CHLD'} = sub { while (waitpid(-1, WNOHANG) == 0) { } };
  44.  
  45. my $exploitsIndex;
  46. my $payloadsIndex;
  47. my $encodersIndex;
  48. my $nopsIndex;
  49.  
  50. my $exploits;
  51. my $eclasses;
  52. my $payloads;
  53. my $encoders;
  54. my $nops;
  55.  
  56. my %opts;
  57. getopts('hvqs:', \%opts);
  58.  
  59. Usage() if($opts{'h'});
  60. Version() if($opts{'v'});
  61.  
  62. my $state = {'Mode' => 'Main'};
  63.  
  64. # load the modules
  65. Load();
  66.  
  67. my $console = Pex::PsuedoShell->new('Metasploit Console', 'msf > ', 0);
  68. $console->tabCompletion(\&xTabCompletion);
  69.  
  70. # configure the last exploit
  71. if ( (my $le = $ui->GetEnv('LastModule')) ) {
  72.     $state->{'Mode'} = 'Exploit';
  73.     $state->{'Exploit'}->{'Name'} = $le;
  74.     gUse('use', $le);
  75. }
  76.         
  77. # virtual command table
  78. my %virtualCmds = ();
  79.  
  80. # global command tables
  81. my %globalCmds =
  82. (
  83.     'version'   => [\&gVersion,       "Show console version"],
  84.     'help'      => [\&gHelp,          "Show the main console help"],
  85.     '?'         => [\&gHelp,          "Show the main console help"],
  86.     'quit'      => [\&gExit,          "Exit the console"],
  87.     'exit'      => [\&gExit,          "Exit the console"],
  88.     'use'       => [\&gUse,           "Select an exploit by name"],
  89.     'info'      => [\&gInfo,          "Display detailed exploit or payload information"],
  90.     'cd'        => [\&gChdir,         "Change working directory"],
  91.     'save'      => [\&gSave,          "Save configuration to disk"],
  92.     'setg'      => [\&gSet,           "Set a global environment variable"],
  93.     'unsetg'    => [\&gUnset,         "Remove a global environment variable"],
  94.     'reload'    => [\&Load,           "Reload exploits and payloads"],
  95. );
  96.  
  97.  
  98. # main mode commands
  99. my %mainCmds =
  100. (
  101.     'show'      => [\&mShow,   "Show available exploits and payloads"],
  102. );
  103.  
  104. # exploit mode commands
  105. my %exploitCmds = 
  106. (
  107.     'set'       => [\&eSet,           "Set a temporary environment variable"],
  108.     'unset'     => [\&eUnset,         "Remove a temporary environment variable"],
  109.     'back'      => [\&eBack,          "Drop back to the main menu"],
  110.     'show'      => [\&eShow,          "Show options, advanced, payloads, or targets"],
  111.     'check'     => [\&eCheck,         "Perform vulnerability check"],
  112.     'rcheck'    => [\&eReloadCheck,   "Perform vulnerability check"],    
  113.     'exploit'   => [\&eExploit,       "Launch the actual exploit"],
  114.     'rexploit'  => [\&eReloadExploit, "Reload and exploit, for us tester types"],
  115. );
  116.  
  117.  
  118. $state->{'LocalAddress'} = Pex::Utils::SourceIP();
  119. xAddAddressCache($state->{'LocalAddress'});
  120.  
  121. if (! defined($opts{'q'})) {
  122.  
  123.     my $username = ($ENV{'USER'} || $ENV{'USERNAME'} || 'unknown');
  124.     Msf::Logging->PrintLine('[' . localtime(time()) . '] msfconsole started on host ' . hostname() . ' by user ' . $username );
  125.     Msf::TextUI::PrintAsciiLogo();
  126.  
  127.     printf("\n+ -- --=[ msfconsole v%s [%d exploits - %d payloads]\n\n", 
  128.            $FRAMEVERSION, 
  129.            scalar(keys(%{$exploits})),
  130.            scalar(keys(%{$payloads}))
  131.     );
  132. }
  133.  
  134. ProcessCmd('use', shift(@ARGV)) if(@ARGV);
  135. ProcessScript($opts{'s'}) if(exists($opts{'s'}));
  136.  
  137. while (1)
  138. {
  139.     SetupCmds();
  140.     last if(!ProcessCmd($console->readCommand()));
  141. }
  142. print "\n";
  143.  
  144. sub SetupCmds {
  145.   %virtualCmds = %globalCmds;
  146.   
  147.   my $stateMode = $state->{'Mode'};
  148.     
  149.   if ($stateMode eq 'Main')    { foreach (keys(%mainCmds)){ $virtualCmds{$_} = $mainCmds{$_} } }
  150.   if ($stateMode eq 'Exploit') { foreach (keys(%exploitCmds)){ $virtualCmds{$_} = $exploitCmds{$_} } }
  151. }
  152.  
  153. sub ProcessCmd {
  154.   my $cmd = shift;
  155.   my @args = @_;
  156.  
  157.   SetupCmds();
  158.  
  159.   return(0) if(!defined($cmd));
  160.  
  161.   if(exists($virtualCmds{$cmd})) {
  162.     $virtualCmds{$cmd}->[0]($cmd, @args);
  163.   }
  164.   else {
  165.     gUnknown($cmd, @args);
  166.   }
  167.   return(1);
  168. }
  169.  
  170. sub ProcessScript {
  171.   my $file = shift;
  172.   open(INFILE, "<$file") or die("Cannot open script: $file: $!\n");
  173.   local $/;
  174.   my $data = <INFILE>;
  175.   close(INFILE);
  176.   foreach my $line (split("\n", $data)) {
  177.     ProcessCmd(Pex::PsuedoShell->parseCommands($line));
  178.   }
  179. }
  180.  
  181. sub Load {
  182.     my $genv = $ui->_Env;
  183.     my $senv = $ui->_TempEnvs;
  184.     my $tenv = $ui->_TempEnv;
  185.  
  186.     $exploitsIndex = $ui->LoadExploits;
  187.     $payloadsIndex = $ui->LoadPayloads;
  188.     $encodersIndex = $ui->LoadEncoders;
  189.     $nopsIndex     = $ui->LoadNops;
  190.     $exploits = { };
  191.     $eclasses = { };
  192.     $payloads = { };
  193.     $encoders = { };
  194.     $nops     = { };
  195.     
  196.     foreach my $key (sort(keys(%{$exploitsIndex}))) {
  197.         $exploits->{$exploitsIndex->{$key}->SelfEndName} = $exploitsIndex->{$key};
  198.         $eclasses->{$exploitsIndex->{$key}->ModuleClass}++;
  199.     }
  200.     
  201.     foreach my $key (sort(keys(%{$encodersIndex}))) {
  202.         $encoders->{$encodersIndex->{$key}->SelfEndName} = $encodersIndex->{$key};
  203.     } 
  204.        
  205.     foreach my $key (sort(keys(%{$nopsIndex}))) {
  206.         $nops->{$nopsIndex->{$key}->SelfEndName} = $nopsIndex->{$key};
  207.     }    
  208.     
  209.     foreach my $key (keys(%{$payloadsIndex})) {
  210.         $payloads->{$payloadsIndex->{$key}->SelfEndName} = $payloadsIndex->{$key};
  211.     }
  212.  
  213.  
  214.     # Important, reload the exploit object in state
  215.     if($state->{'Mode'} eq 'Exploit') {
  216.       my $exploit = $exploits->{$state->{'Exploit'}->{'Name'}};
  217.  
  218.       # check to make sure the module reloaded, it could have had errors..
  219.       if(!$exploit) {
  220.         xMsg('reload', 'Error reloading current exploit, moving back to Main.');
  221.         eBack();
  222.       }
  223.       # ok, call gUse to reload tab completion, etc
  224.       else {
  225.         gUse('use', $state->{'Exploit'}->{'Name'});
  226.       }
  227.     }
  228.     
  229.     $ui->_Env($genv);
  230.     $ui->_TempEnvs($senv);
  231.     $ui->_TempEnv($tenv);
  232. }
  233.  
  234. sub gSave {
  235.     my $cmd = shift;
  236.     if($state->{'Mode'} eq 'Exploit') {
  237.         $ui->SetGlobalEnv('LastModule', $state->{'Exploit'}->{'Name'});
  238.         $ui->SaveTempEnv($state->{'Exploit'}->{'Name'});
  239.     } else {
  240.         $ui->UnsetGlobalEnv('LastModule');
  241.     }
  242.     
  243.     $ui->SaveConfig;
  244.     print "Saved configuration to: " . $ui->ConfigFile . "\n";
  245. }
  246.  
  247. sub gVersion { print "msfconsole version ". Pex::Utils::Rev2Ver($VERSION)."\n" }
  248.  
  249. sub gSet {
  250.     my $cmd = shift;
  251.     if(@_ == 1) {
  252.         print "$_[0]: " . $ui->GetGlobalEnv($_[0]) . "\n";
  253.     }
  254.     elsif(@_ == 2) {
  255.         print "$_[0] -> $_[1]\n";
  256.         $ui->SetGlobalEnv($_[0], $_[1]);
  257.     }
  258.     else {
  259.         foreach (sort(keys(%{$ui->GetGlobalEnv}))) {
  260.             print "$_: " . $ui->GetGlobalEnv($_) . "\n";
  261.         }
  262.     }
  263. }
  264.  
  265. sub gUnset
  266. {
  267.     my ($cmd, $key) = @_;
  268.  
  269.     if(!defined($key))
  270.     {
  271.         my $ok = xAskYN('Clear env? [yes/no]: ');
  272.         return if $ok ne 'yes';
  273.         $ui->UnsetGlobalEnv;
  274.     }
  275.     $ui->UnsetGlobalEnv($key);
  276. }
  277.  
  278. sub eSet {
  279.     my $cmd = shift;
  280.     if(@_ == 1) {
  281.         print "$_[0]: " . $ui->GetTempEnv($_[0]) . "\n";
  282.     }
  283.     elsif(@_ == 2) {
  284.         print "$_[0] -> $_[1]\n";
  285.         $ui->SetTempEnv($_[0], $_[1]);
  286.     }
  287.     else {
  288.         foreach (sort(keys(%{$ui->GetTempEnv}))) {
  289.             print "$_: " . $ui->GetTempEnv($_) . "\n";
  290.         }
  291.     }
  292.     
  293.     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
  294.     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload) {
  295.         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
  296.     }
  297.     $prompt .= ' > ';
  298.     $console->_prompt($prompt);
  299. }
  300.  
  301. sub eUnset
  302. {
  303.     my ($cmd, $key) = @_;
  304.  
  305.     if(!defined($key))
  306.     {
  307.         my $ok = xAskYN('Clear temporary env? [yes/no]: ');
  308.         return if $ok ne 'yes';
  309.         $ui->UnsetTempEnv;
  310.     }
  311.     $ui->UnsetTempEnv($key);
  312.     
  313.     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
  314.     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload) {
  315.         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
  316.     }
  317.     $prompt .= ' > ';
  318.     $console->_prompt($prompt);
  319. }
  320.  
  321.  
  322. sub gExit
  323. {
  324.     Msf::Logging->PrintLine('[' . localtime(time()) . '] msfconsole closed' );
  325.     POSIX::_exit(0) if($ui->GetEnv('AlternateExit') == 1);
  326.     if($ui->GetEnv('AlternateExit') == 2) {
  327.       exec('true');
  328.     }
  329.     exit(0);
  330. }
  331.  
  332. sub gUnknown
  333. {
  334.     my ($cmd, @args) = @_;
  335.     
  336.     if (! xCheckSystemCommand($cmd)) 
  337.     {
  338.         xMsg($cmd, "command not found");
  339.     } else {
  340.         my $cmdline = "$cmd ". join(" ", @args);
  341.         Msf::Logging->PrintLine('[' . localtime(time()) . "] executing system command line '$cmdline'");    
  342.         system($cmdline);
  343.     }
  344. }
  345.  
  346. sub gHelp
  347. {
  348.     my ($cmd, @args) = @_;
  349.     
  350.     my $col = Msf::ColPrint->new(8, 6);
  351.     print "\nMetasploit Framework " . $state->{'Mode'}  . " Console Help\n";
  352.     print   "======================================\n\n";
  353.     foreach my $cmd (sort(keys(%virtualCmds)))
  354.     {
  355.         $col->AddRow($cmd, $virtualCmds{$cmd}->[1]);
  356.     }
  357.     print $col->GetOutput . "\n";
  358. }
  359.  
  360. sub gUse 
  361. {
  362.     my ($cmd, @args) = @_;
  363.     if (! exists($exploits->{$args[0]}))
  364.     {
  365.         xMsg("use", "please specify a valid exploit name");
  366.         return;
  367.     }
  368.     
  369.     my $exploit = $exploits->{$args[0]};
  370.     
  371.     # switch to exploit mode
  372.     $state->{'Mode'} = 'Exploit';
  373.     
  374.     # wipe out any previous exploit state
  375.     delete($state->{'Exploit'});
  376.     
  377.     $state->{'Exploit'}->{'Exploit'} = $exploit;
  378.     $state->{'Exploit'}->{'Name'} = $args[0];
  379.     $state->{'Exploit'}->{'Payloads'} = xValidPayloads($exploit);
  380.  
  381.     $ui->LoadTempEnv($args[0]);
  382.  
  383.     if(defined($exploit->UseMessage)) {
  384.       print $exploit->UseMessage . "\n";
  385.     }
  386.     
  387.     my $prompt = 'msf '.$state->{'Exploit'}->{'Name'};
  388.     if ($ui->GetEnv('PAYLOAD') && $state->{'Exploit'}->{'Exploit'}->Payload)
  389.     {
  390.         $prompt .= '('.$ui->GetEnv('PAYLOAD').')';
  391.     }
  392.     $prompt .= ' > ';
  393.     $console->_prompt($prompt);
  394. }
  395.  
  396. sub eBack
  397. {
  398.     $ui->SaveTempEnv($state->{'Exploit'}->{'Name'});
  399.     $ui->UnsetTempEnv;
  400.     $state->{'Mode'} = 'Main';
  401.     $console->_prompt("msf > ");
  402. }
  403.  
  404. sub gChdir
  405. {
  406.     my ($cmd, @args) = @_;
  407.     
  408.     if (! $args[0])
  409.     {
  410.         chdir($ENV{'HOME'});
  411.         return;
  412.     }
  413.     
  414.     if (chdir($args[0]))
  415.     {
  416.         xMsg("chdir", "changed to directory $args[0]");
  417.     } else {
  418.         xMsg("chdir", "failed to change directory $!");
  419.     }
  420. }
  421.  
  422. sub gInfo {
  423.   my $cmd = shift;
  424.   my @args = @_;
  425.   my $module;
  426.   my $type;
  427.  
  428.   # Support old info exploit/payload syntax
  429.   if(@args == 2) {
  430.     $module = $args[1];
  431.     $type = $args[0];
  432.   }
  433.   elsif(@args == 1) {
  434.     $module = $args[0];
  435.   }
  436.     
  437.   if(!defined($module) || ($type ? $type !~ /^(encoder|exploit|payload|nop)$/ : 0)) {
  438.     xMsg("info", "usage: info [type] <module name>");
  439.     return;
  440.   }
  441.  
  442.   if($exploits->{$module} && ($type ? $type eq 'exploit' : 1)) {
  443.     print "\n" . $ui->DumpExploitSummary($exploits->{$module});
  444.   }
  445.   elsif($payloads->{$module} && ($type ? $type eq 'payload' : 1)) {
  446.     print "\n" . $ui->DumpPayloadSummary($payloads->{$module});
  447.   }
  448.  
  449.   # Kinda a hack, we rebuild the keys for exploits and payloads, but
  450.   # not for nops or encoders...
  451.   elsif($encoders->{$module} && ($type ? $type eq 'encoder' : 1)) {
  452.     print "\n" . $ui->DumpEncoderSummary($encoders->{$module});
  453.   }
  454.   elsif($nops->{$module} && ($type ? $type eq 'nop' : 1)) {
  455.     print "\n" . $ui->DumpNopSummary($nops->{$module});
  456.   }
  457.   
  458.   else {
  459.     xMsg("info", "invalid module name");
  460.   }
  461. }
  462.  
  463. sub mShow 
  464. {
  465.     my ($cmd, @args) = @_;
  466.     my $c = $state->{'CONF'};
  467.     
  468.     if (lc($args[0]) eq "exploits")
  469.     {
  470.         print "\nMetasploit Framework Loaded Exploits\n";
  471.         print   "====================================\n\n";
  472.         
  473.         print $ui->DumpExploits(2, $exploits, $args[1]) . "\n";
  474.         return;
  475.     }
  476.     
  477.     if (lc($args[0]) eq "payloads")
  478.     {
  479.         print "\nMetasploit Framework Loaded Payloads\n";
  480.         print   "====================================\n\n";
  481.         
  482.         print $ui->DumpPayloads(2, $payloads) . "\n";
  483.         return;
  484.     }
  485.  
  486.     if (lc($args[0]) eq "encoders")
  487.     {
  488.         print "\nMetasploit Framework Loaded Encoders\n";
  489.         print   "====================================\n\n";
  490.         
  491.         print $ui->DumpEncoders(2, $encoders) . "\n";
  492.         return;
  493.     }
  494.  
  495.     if (lc($args[0]) eq "nops")
  496.     {
  497.         print "\nMetasploit Framework Loaded Nop Engines\n";
  498.         print   "=======================================\n\n";
  499.         
  500.         print $ui->DumpNops(2, $nops) . "\n";
  501.         return;
  502.     }
  503.  
  504.     if (lc($args[0]) eq "config")
  505.     {
  506.         print "\nMetasploit Framework Configuration\n";
  507.         print   "====================================\n\n";
  508.         
  509.         foreach my $v (sort(keys(%{$c}))) {
  510.             print "  $v" . (" " x (30-length($v))) . $c->{$v} ."\n";
  511.         }
  512.         print "\n";
  513.         return;
  514.     }
  515.  
  516.     xMsg("show", "requires an option: 'exploits', 'payloads', 'encoders', or 'nops'");
  517. }
  518.  
  519.  
  520. sub eShow 
  521. {
  522.     my ($cmd, @args) = @_;
  523.     if (lc($args[0]) eq 'options')  { eOptions();  return }
  524.     if (lc($args[0]) eq 'advanced') { eAdvanced(); return }
  525.     if (lc($args[0]) eq 'targets')  { eTargets();  return }
  526.     if (lc($args[0]) eq 'payloads') { ePayloads(); return }
  527.  
  528.     xMsg("show", "specify 'targets', 'payloads', 'options', or 'advanced'");
  529.  
  530. }
  531.  
  532. sub ePayloads {
  533.   SaveTemp();
  534.   FillTemp();
  535.   $ui->Payloads;
  536.   RestoreTemp();
  537. }
  538. sub eOptions {
  539.   SaveTemp();
  540.   FillTemp();
  541.   $ui->Options;
  542.   RestoreTemp();
  543. }
  544. sub eAdvanced {
  545.   SaveTemp();
  546.   FillTemp();
  547.   $ui->AdvancedOptions;
  548.   RestoreTemp();
  549. }
  550. sub eTargets  {
  551.   SaveTemp();
  552.   FillTemp();
  553.   $ui->Targets;
  554.   RestoreTemp();
  555. }
  556.  
  557. sub eCheck {
  558.   return if($state->{'Mode'} ne 'Exploit');
  559.   xUpdateAddrCache();
  560.   SaveTemp();
  561.   FillTemp();
  562.   $ui->Check;
  563.   RestoreTemp();
  564. }
  565.  
  566. sub eReloadCheck {
  567.   Load();
  568.   return eCheck(@_);
  569. }
  570.  
  571. sub eExploit {
  572.   return if($state->{'Mode'} ne 'Exploit');
  573.   xUpdateAddrCache();
  574.   SaveTemp();
  575.   FillTemp();
  576.   $ui->Exploit;
  577.   RestoreTemp();
  578. }
  579.  
  580. sub eReloadExploit {
  581.   Load();
  582.   return eExploit(@_);
  583. }
  584.  
  585. sub xMsg
  586. {
  587.     my ($loc, $msg) = @_;
  588.     print STDERR "msfconsole: $loc: $msg\n";
  589. }
  590.  
  591. sub xValidPayloads
  592. {
  593.     my $exploit = shift;
  594.     if($exploit->Payload) {
  595.       $state->{'Exploit'}->{'Payloads'} = $ui->MatchPayloads($exploit, $payloads);
  596.       return $state->{'Exploit'}->{'Payloads'};
  597.     }
  598.     return;
  599. }
  600.  
  601. sub xCheckSystemCommand
  602. {
  603.     my $cmd = shift;
  604.     return(1) if -e $cmd;
  605.     foreach my $d (split(/:/, $ENV{'PATH'})) { 
  606.     
  607.         if ($^O eq 'cygwin') {
  608.             return(1) if -e "$d/$cmd";
  609.         } else {
  610.             return(1) if -x "$d/$cmd";
  611.         }
  612.     }
  613.     return(0);
  614. }
  615.  
  616. sub xGetAddressCache
  617. {
  618.     my $cache = $state->{'CacheAddress'};
  619.     return keys(%{$cache});
  620. }
  621.  
  622. sub xAddAddressCache
  623. {
  624.     my $addr = shift;
  625.     $state->{'CacheAddress'}->{$addr}++
  626. }
  627.  
  628. sub xUpdateAddrCache 
  629. {
  630.     my $x = $state->{'Exploit'}->{'Exploit'};
  631.     my $p = $ui->GetEnv('PAYLOAD');
  632.     my %options = ();
  633.  
  634.     
  635.     # create a list of all exploit options of type ADDR
  636.     foreach (keys(%{$x->UserOpts})) {
  637.         next if $x->UserOpts->{$_}->[1] ne 'ADDR';
  638.         $options{$_}++;
  639.     }
  640.     foreach (keys(%{$x->Advanced})) {
  641.         next if $x->Advanced->{$_}->[1] ne 'ADDR';
  642.         $options{$_}++;
  643.     }  
  644.  
  645.     # create a list of all payload options of type ADDR
  646.     if ($x->Payload && $p && exists($payloads->{$p}))
  647.     {
  648.         $p = $payloads->{$p};
  649.     $p->_Load;
  650.         foreach (keys(%{$p->UserOpts})) {
  651.             next if $p->UserOpts->{$_}->[1] ne 'ADDR';
  652.             $options{$_}++;
  653.         }        
  654.         foreach (keys(%{$p->Advanced})) {
  655.             next if $p->Advanced->{$_}->[1] ne 'ADDR';
  656.             $options{$_}++;
  657.         }
  658.     }
  659.     
  660.     # scan environments and add to the cache
  661.     foreach (keys(%options)) {
  662.         my $value = $ui->GetTempEnv($_) || $ui->GetEnv($_) || undef;
  663.         next if ! $value;
  664.         $state->{'CacheAddress'}->{$value}++;
  665.     }
  666. }
  667.  
  668. sub xAskYN {
  669.     my $quest    = shift;
  670.     my $cinp    = IO::Handle->new_from_fd(0, '<');
  671.     my $cout    = IO::Handle->new_from_fd(1, '>');
  672.     my $iblock    = $cinp->blocking;
  673.     
  674.     $cinp->blocking(1);
  675.  
  676.     my $res = 'run';
  677.     while ($res && $res ne 'yes' && $res ne 'no') {
  678.         $cout->printflush($quest);
  679.         if ( defined($res = $cinp->getline)) {
  680.             chomp($res);
  681.             $res = lc($res);
  682.         } 
  683.         else { $cout->printflush("\nError reading from input: $!\n"); }
  684.     }
  685.     $cinp->blocking($iblock);
  686.     return $res;
  687. }
  688.  
  689.  
  690. #
  691. # TAB COMPLETION ROUTINES
  692. #
  693.  
  694. sub xCreateSetList
  695. {
  696.     if ($state->{"Mode"} eq "Main") { return keys(%{$ui->GetGlobalEnv}) } 
  697.     
  698.     if ($state->{"Mode"} eq "Exploit") 
  699.     {
  700.         my %options = ();
  701.         
  702.         my $x = $state->{'Exploit'}->{'Exploit'};
  703.         my $p = $ui->GetEnv('PAYLOAD');
  704.         
  705.         foreach (keys(%{$x->UserOpts})) { $options{$_}++ }
  706.         foreach (keys(%{$x->Advanced})) { $options{$_}++ }
  707.         
  708.         if ($x->Payload && $p && exists($payloads->{$p}))
  709.         {
  710.             $p = $payloads->{$p};
  711.         $p->_Load;
  712.             foreach (keys(%{$p->UserOpts})) { $options{$_}++ }
  713.             foreach (keys(%{$p->Advanced})) { $options{$_}++ }
  714.         }
  715.          
  716.         if ($x->Payload) { $options{"PAYLOAD"}++ }
  717.         if ($x->TargetsList) { $options{"TARGET"}++  }
  718.  
  719.         foreach my $e (keys(%{ $ui->GetEnv })) {
  720.             $options{$e}++;
  721.         }
  722.         
  723.         foreach my $e (keys(%{ $ui->GetTempEnv })) {
  724.             $options{$e}++;
  725.         }   
  726.  
  727.         return(keys(%options));
  728.     }
  729. }
  730.  
  731. sub xCreateSetValueList
  732. {
  733.     if ($state->{"Mode"} eq "Main") { return ' ' } 
  734.     
  735.     if ($state->{"Mode"} eq "Exploit") 
  736.     {
  737.         my %results = ();
  738.         
  739.         my $n = $state->{'SetName'};
  740.         my $x = $state->{'Exploit'}->{'Exploit'};
  741.         my $v = $state->{'Exploit'}->{'Payloads'};
  742.         my $p = $ui->GetEnv('PAYLOAD');
  743.  
  744.         if ($x->Payload && $p && exists($payloads->{$p})) { $p = $payloads->{$p} }
  745.         
  746.         if (uc($n) eq "PAYLOAD") { return keys(%{$v}) }
  747.         
  748.         if (uc($n) eq "TARGET")
  749.         {
  750.             my $tidx = 0;
  751.             foreach ($x->TargetsList) { $results{$tidx}++ ; $tidx++;}
  752.             return keys(%results);
  753.         }
  754.         
  755.         my ($req, $type, $desc, $dflt);
  756.         
  757.         if (exists($x->UserOpts->{$n})) {
  758.             ($req, $type, $desc, $dflt) = @{$x->UserOpts->{$n}};  
  759.         }
  760.         
  761.         if (exists($x->Advanced->{$n})) {
  762.             ($req, $type) = (0, 'DATA');
  763.             ($dflt, $desc) = @{$x->Advanced->{$n}};
  764.         }
  765.                 
  766.         if ($x->Payload && $p && exists($p->UserOpts->{$n})) {
  767.             ($req, $type, $desc, $dflt) = @{$p->UserOpts->{$n}};  
  768.         }
  769.                 
  770.         if ($x->Payload && $p && exists($p->Advanced->{$n})) {
  771.             ($req, $type) = (0, 'DATA');
  772.             ($dflt, $desc) = @{$p->Advanced->{$n}};
  773.         }
  774.         
  775.         if ($dflt) { return ($dflt) }
  776.         
  777.         if ($type eq "ADDR") { return xGetAddressCache() }
  778.         if ($type eq "BOOL") { return ("TRUE", "FALSE") }
  779.         if ($type eq "FILE") { return undef }
  780.         if ($type eq "PATH") { return undef }
  781.         return ' ';
  782.     }
  783. }
  784.  
  785. sub xTabCompletion
  786. {
  787.     my ($text, $line, $start, $end) = @_;
  788.     my ($cmd, @args) = split(/\s+/, $line);
  789.     
  790.     # default to match of space
  791.     $state->{'TabVals'} = [' '];
  792.     
  793.     # this handles command matching
  794.     if ($start == 0) { $state->{'TabVals'} = [sort(keys(%virtualCmds))] }
  795.     
  796.     if (lc($cmd) eq "use") { $state->{'TabVals'} = [sort(keys(%{$exploits}))] }
  797.     
  798.     if (lc($cmd) eq "show")
  799.     {
  800.         if ($state->{'Mode'} eq 'Main') {
  801.             
  802.             # Handle ModuleClass tab completion stuff
  803.             if ($args[0] eq 'exploits') {
  804.                 $state->{'TabVals'} = [sort(keys(%{$eclasses}))];
  805.             }
  806.             # Default to the standard show options
  807.             else {
  808.                 $state->{'TabVals'} = ['exploits', 'payloads', 'encoders', 'nops'];
  809.             }
  810.         }
  811.         
  812.         if ($state->{'Mode'} eq 'Exploit') {
  813.             $state->{'TabVals'} = ['advanced', 'options', 'targets', 'payloads'] 
  814.         }
  815.     }
  816.     
  817.     if (lc($cmd) eq "info")
  818.     {
  819.         # display variables if no args are specified
  820.         if (! $args[0] || (! $args[1] && ($args[0] && $text))) { 
  821.             
  822.             my %allmods;
  823.             for (keys(%{$exploits}), keys(%{$payloads}), keys(%{$encoders}), keys(%{$nops})) {
  824.                 $allmods{$_}++;
  825.             }
  826.             
  827.             $state->{'TabVals'} = ['exploit', 'payload', 'encoder', 'nop', sort(keys(%allmods))] 
  828.         }
  829.         if (! $args[1] || (! $args[2] && ($args[1] && $text)))
  830.         {
  831.             if ($args[0] eq "exploit") { $state->{'TabVals'} = [sort(keys(%{$exploits}))] }
  832.             if ($args[0] eq "payload") { $state->{'TabVals'} = [sort(keys(%{$payloads}))] }
  833.             if ($args[0] eq "encoder") { $state->{'TabVals'} = [sort(keys(%{$encoders}))] }
  834.             if ($args[0] eq "nop"    ) { $state->{'TabVals'} = [sort(keys(%{$nops}))] }            
  835.         }
  836.     }
  837.         
  838.     if (
  839.         ($state->{'Mode'} eq "Main"    && lc($cmd) =~ /^(un|)setg$/) ||
  840.         ($state->{'Mode'} eq "Exploit" && lc($cmd) =~ /^(un|)set$/)
  841.        )
  842.     {
  843.         # display variables if no args are specified
  844.         if (! $args[0] || (! $args[1] && ($args[0] && $text)))
  845.         {
  846.             $state->{'TabVals'} = [sort(xCreateSetList())];
  847.         } elsif (! $args[1] || (! $args[2] && ($args[1] && $text)))
  848.         {
  849.             $state->{'SetName'} = $args[0];
  850.             $state->{'TabVals'} = [sort(xCreateSetValueList())];
  851.         }
  852.     }
  853.     
  854.     # revert to file completion for non-commands
  855.     if (! scalar(@{$state->{'TabVals'}}) && ! exists($virtualCmds{$cmd})) {
  856.         $state->{'TabVals'} = []; 
  857.     }
  858.     
  859.     
  860.  
  861.     my @matches = $console->_term->completion_matches($text, \&xTabCompletionMatcher);
  862.     return(@matches); 
  863. }
  864.  
  865.  
  866. # This is a localized closure for matching speed, this routine has been borrowed
  867. # from http://lists.n0i.net/pipermail/perl/2003-October/000015.html
  868. {
  869.     my $list_index;
  870.     my @name;
  871.     
  872.     sub xTabCompletionMatcher
  873.     {
  874.         my ($text, $mstate) = @_;
  875.         $text = quotemeta($text);
  876.  
  877.         # If this is a new word to complete, initialize now.  This
  878.         # includes saving the length of TEXT for efficiency, and
  879.         # initializing the index variable to 0.
  880.  
  881.         unless ($mstate) {
  882.             $list_index = 0;
  883.             @name = @{$state->{'TabVals'}};
  884.             return undef if (scalar(@name) == 0);
  885.         }
  886.  
  887.         # Return the next name which partially matches from the
  888.         # command list.
  889.         while ($list_index <= $#name) {
  890.             $list_index++;
  891.             return $name[$list_index - 1]
  892.                 if ($name[$list_index - 1] =~ /^$text/);
  893.         }
  894.  
  895.         # If no names matched, then return NULL.
  896.         return undef;
  897.     }
  898. }
  899.  
  900. sub SaveTemp {
  901.   $ui->SaveTempEnv('_Save');
  902. }
  903.  
  904. sub RestoreTemp {
  905.   $ui->LoadTempEnv('_Save');
  906.   $ui->DeleteTempEnv('_Save');
  907. }
  908.  
  909. sub FillTemp {
  910.   $ui->SetTempEnv('_ExploitsIndex', $exploitsIndex);
  911.   $ui->SetTempEnv('_PayloadsIndex', $payloadsIndex);
  912.   $ui->SetTempEnv('_Encoders', $encodersIndex);
  913.   $ui->SetTempEnv('_Nops', $nopsIndex);
  914.  
  915.   $ui->SetTempEnv('_Exploits', $exploits);
  916.   $ui->SetTempEnv('_Payloads', $payloads);
  917.  
  918.   my $exploit = $state->{'Exploit'}->{'Exploit'};
  919.   $ui->SetTempEnv('_Exploit', $exploit);
  920.   
  921.   $ui->SetTempEnv('_UI', $ui);
  922.  
  923.   # XXX added by spoon, maybe this should be looked at...
  924.   # applying the AutoOpts settings to the local temp env we have setup,
  925.   # specifically this fixes things like the EXITFUNC display issues
  926.   # this will later get called again in Exploit::Prepare, maybe we should
  927.   # look into just having it done once....
  928.   $exploit->ApplyAutoOpts;
  929.  
  930.   # setup payload data if exploit requires a payload
  931.   if($exploit->Payload) {
  932.     my $payloadName = $ui->GetEnv('PAYLOAD');
  933.     $ui->SetTempEnv('_PayloadName', $payloadName);
  934.     my $validPayloads = $ui->MatchPayloads($exploit, $payloads);
  935.     my $payload = $validPayloads->{$payloadName};
  936.     # make sure the OO stuff is good for whoever might use this...
  937.     $payload->_Load if($payload);
  938.     $ui->SetTempEnv('_Payload', $payload);
  939.     $ui->SetTempEnv('_ValidPayloads', $validPayloads);
  940.   }
  941.   else {
  942.     $ui->SetTempEnv('_PayloadName', undef);
  943.     $ui->SetTempEnv('_Payload', undef);
  944.     $ui->SetTempEnv('_ValidPayloads', undef);
  945.   }
  946. }
  947.  
  948. sub Usage {
  949.     print STDERR qq{
  950.   Usage: $0 <options> <exploit>
  951. Options:
  952.          -h             You're looking at me baby
  953.          -v             List version information
  954.          -s   <file>    Process file of console commands
  955.          -q             No splash screen on startup
  956.  
  957. };
  958.     exit(0);
  959. }
  960.  
  961. sub Version {
  962.     my $ver = Pex::Utils::Rev2Ver($VERSION);
  963.     print STDERR qq{
  964.    Framework Version:  $FRAMEVERSION
  965.   Msfconsole Version:  $ver
  966.  
  967. };
  968.  
  969.   exit(0);
  970. }
  971.